﻿namespace TestTool.HttpTransport.Internals.Http
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.CompilerServices;
    using System.Security.Cryptography;
    using System.Text;
    using TestTool.HttpTransport.Interfaces;

    internal class HttpDigest
    {
        private static string _a1;
        private const string ALGORITHM = "algorithm";
        private const string MD5 = "MD5";
        private const string MD5SESS = "MD5-sess";
        private const string NONCE = "nonce";
        private const string OPAQUE = "opaque";
        private const string REALM = "realm";
        private const string STALE = "stale";
        public const string WWWAUTHENTICATEHEADER = "WWW-Authenticate";

        public static string CreateDigestAuthenticationHeader(DigestAuthenticationParameters authenticationParameters, DigestTestingSettings testingSettings)
        {
            string str = string.Empty;
            string userName = authenticationParameters.UserName;
            string password = authenticationParameters.Password;
            string address = authenticationParameters.Address;
            HttpPacket challenge = authenticationParameters.Challenge;
            if (!challenge.Headers.ContainsKey("WWW-Authenticate"))
            {
                return str;
            }
            string str5 = challenge.Headers["WWW-Authenticate"];
            int index = str5.IndexOf(' ');
            str5.Substring(0, index).Trim();
            string str6 = str5.Substring(index).Trim();
            List<int> list = new List<int>();
            bool flag = false;
            for (int i = 0; i < str6.Length; i++)
            {
                char ch = str6[i];
                if (ch == '"')
                {
                    flag = !flag;
                }
                else if ((ch == ',') && !flag)
                {
                    list.Add(i);
                }
            }
            list.Add(str6.Length);
            Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
            int startIndex = 0;
            foreach (int num4 in list)
            {
                string[] strArray = str6.Substring(startIndex, num4 - startIndex).Split(new char[] { '=' });
                if (strArray.Length != 2)
                {
                    throw new ApplicationException(string.Format("Invalid authentication header: {0}", str5));
                }
                dictionary.Add(Unquote(strArray[0]), strArray[1].Trim());
                startIndex = num4 + 1;
            }
            StringBuilder builder = new StringBuilder("Authorization: Digest ");
            if ((testingSettings == null) || !testingSettings.UserNameMissing)
            {
                builder.AppendFormat("username=\"{0}\", ", userName);
            }
            if ((testingSettings == null) || !testingSettings.RealmMissing)
            {
                builder.AppendFormat("{0}={1}, ", "realm", dictionary["realm"]);
            }
            string str8 = "MD5";
            if (dictionary.ContainsKey("algorithm"))
            {
                str8 = dictionary["algorithm"];
            }
            builder.AppendFormat("qop=\"auth\", algorithm=\"{0}\", ", str8);
            if ((testingSettings == null) || !testingSettings.UriMissing)
            {
                builder.AppendFormat("uri=\"{0}\", ", address);
            }
            if ((testingSettings == null) || !testingSettings.NonceMissing)
            {
                builder.AppendFormat("{0}={1}, nc=00000001, ", "nonce", dictionary["nonce"]);
            }
            string nonce = GetNonce();
            builder.AppendFormat("cnonce=\"{0}\", ", nonce);
            if (dictionary.ContainsKey("opaque"))
            {
                builder.AppendFormat("{0}={1}, ", "opaque", dictionary["opaque"]);
            }
            if ((testingSettings == null) || !testingSettings.ResponseMissing)
            {
                string str10 = Unquote(dictionary["realm"]);
                string str11 = Unquote(dictionary["nonce"]);
                string val = string.Format("{0}:{1}:{2}", userName, str10, password);
                if (str8 == "MD5-sess")
                {
                    if (string.IsNullOrEmpty(_a1))
                    {
                        _a1 = GetMD5HashBinHex(val);
                    }
                    val = string.Format("{0}:{1}:{2}", _a1, str11, nonce);
                }
                string str13 = string.Format("POST:{0}", address);
                string str14 = GetMD5HashBinHex(val);
                string str15 = GetMD5HashBinHex(str13);
                string str17 = GetMD5HashBinHex(string.Format("{0}:{1}:00000001:{2}:auth:{3}", new object[] { str14, str11, nonce, str15 }));
                builder.AppendFormat("response=\"{0}\"", str17);
            }
            return builder.ToString();
        }

        private static string GetHex(byte[] bytes)
        {
            return BitConverter.ToString(bytes).Replace("-", "");
        }

        private static string GetMD5HashBinHex(string val)
        {
            Encoding encoding = new ASCIIEncoding();
            byte[] buffer = new MD5CryptoServiceProvider().ComputeHash(encoding.GetBytes(val));
            string str = "";
            for (int i = 0; i < buffer.Length; i++)
            {
                str = str + string.Format("{0:x02}", buffer[i]);
            }
            return str;
        }

        private static string GetNonce()
        {
            byte[] data = new byte[0x10];
            RandomNumberGenerator.Create().GetBytes(data);
            return GetHex(data);
        }

        private static string Unquote(string value)
        {
            return value.Trim(new char[] { ' ', '"' });
        }

        internal class DigestAuthenticationParameters
        {
            public string Address { get; set; }

            public HttpPacket Challenge { get; set; }

            public string Password { get; set; }

            public string UserName { get; set; }
        }
    }
}

